/****************************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.  The
 * ASF licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 ****************************************************************************/

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "mem.h"

#include <lwip/tcpip.h>
#include <lwip/sockets.h>
#include <lwip/netdb.h>

#include "bl_fw_api.h"
#include "wifi_mgmr_ext.h"
#include "wifi_mgmr.h"

#include "bflb_irq.h"
#include "bflb_uart.h"

#include "bl616_glb.h"
#include "rfparam_adapter.h"

#include "board.h"
#include "shell.h"

#define DBG_TAG "MAIN"
#include "log.h"

struct bflb_device_s *gpio;

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

#define WIFI_STACK_SIZE  (1536)
#define TASK_PRIORITY_FW (16)

/****************************************************************************
 * Private Types
 ****************************************************************************/

/****************************************************************************
 * Private Data
 ****************************************************************************/

static struct bflb_device_s *uart0;
static uint32_t sta_ConnectStatus = 0;
static uint8_t sta_ConnectStatus1 = 0;
static TaskHandle_t wifi_fw_task;
int sock_client = -1;
#define MAXSIZE 1024
#define beserver_ip    "bemfa.com"  //"192.168.110.233" //"bemfa.com" //巴法云服务器地址默认即可
#define beserver_port "8344" //服务器端口，tcp创客云端口8344
//static const char* UID = "********";  //用户私钥，可在控制台获取,修改为自己的UID
//static const char* TOPIC = "******";         //主题名字，可在控制台新建
static const char subscribe[] = "cmd=1&uid=******&topic=******\r\n"; //构建订阅指令
static const char Keep_alive_str[] = "cmd=7&uid=****&type=1\r\n";//心跳数据
struct sockaddr_in  client_addr;
socklen_t sin_size;
static wifi_conf_t conf = {
    .country_code = "CN",
};

/****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

/****************************************************************************
 * Functions
 ****************************************************************************/

int wifi_start_firmware_task(void)
{
    LOG_I("Starting wifi ...\r\n");

    /* enable wifi clock */

    GLB_PER_Clock_UnGate(GLB_AHB_CLOCK_IP_WIFI_PHY | GLB_AHB_CLOCK_IP_WIFI_MAC_PHY | GLB_AHB_CLOCK_IP_WIFI_PLATFORM);
    GLB_AHB_MCU_Software_Reset(GLB_AHB_MCU_SW_WIFI);

    /* set ble controller EM Size */

    GLB_Set_EM_Sel(GLB_WRAM160KB_EM0KB);

    if (0 != rfparam_init(0, NULL, 0)) {
        LOG_I("PHY RF init failed!\r\n");
        return 0;
    }

    LOG_I("PHY RF init success!\r\n");

    /* Enable wifi irq */

    extern void interrupt0_handler(void);
    bflb_irq_attach(WIFI_IRQn, (irq_callback)interrupt0_handler, NULL);
    bflb_irq_enable(WIFI_IRQn);

    xTaskCreate(wifi_main, (char *)"fw", WIFI_STACK_SIZE, NULL, TASK_PRIORITY_FW, &wifi_fw_task);

    return 0;
}

void wifi_event_handler(uint32_t code)
{
    sta_ConnectStatus = code;
    switch (code) {
        case CODE_WIFI_ON_INIT_DONE: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_INIT_DONE\r\n", __func__);
            wifi_mgmr_init(&conf);
        } break;
        case CODE_WIFI_ON_MGMR_DONE: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_MGMR_DONE\r\n", __func__);
        } break;
        case CODE_WIFI_ON_SCAN_DONE: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_SCAN_DONE\r\n", __func__);
            wifi_mgmr_sta_scanlist();
        } break;
        case CODE_WIFI_ON_CONNECTED: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_CONNECTED\r\n", __func__);
            void mm_sec_keydump();
            mm_sec_keydump();
        } break;
        case CODE_WIFI_ON_GOT_IP: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_GOT_IP\r\n", __func__);
            LOG_I("[SYS] Memory left is %d Bytes\r\n", kfree_size());
        } break;
        case CODE_WIFI_ON_DISCONNECT: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_DISCONNECT\r\n", __func__);
        } break;
        case CODE_WIFI_ON_AP_STARTED: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STARTED\r\n", __func__);
        } break;
        case CODE_WIFI_ON_AP_STOPPED: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STOPPED\r\n", __func__);
        } break;
        case CODE_WIFI_ON_AP_STA_ADD: {
            LOG_I("[APP] [EVT] [AP] [ADD] %lld\r\n", xTaskGetTickCount());
        } break;
        case CODE_WIFI_ON_AP_STA_DEL: {
            LOG_I("[APP] [EVT] [AP] [DEL] %lld\r\n", xTaskGetTickCount());
        } break;
        default: {
            LOG_I("[APP] [EVT] Unknown code %u \r\n", code);
        }
    }
}
uint8_t wifi_connect()
{
    char* ssid = "******";
    char* passwd = "*****";

    uint32_t ipv4_addr = 0;

    if (wifi_mgmr_sta_state_get() == 1) {
        wifi_sta_disconnect();
    }
    if (wifi_sta_connect(ssid, passwd, NULL, NULL, 0, 0, 0, 1)) {
        return 4;
    }

    //等待连接成功
    sta_ConnectStatus = 0;
    for (int i = 0;i<10*30;i++) 
   // while(true) 
    {
        vTaskDelay(100);
        switch (sta_ConnectStatus) 
        {
            case CODE_WIFI_ON_CONNECTED:	//连接成功(表示wifi sta状态的时候表示同时获取IP(DHCP)成功，或者使用静态IP)
                LOG_I("CODE_WIFI_ON_CONNECTED\r\n");
                break;
            case CODE_WIFI_ON_DISCONNECT:	//连接失败（超过了重连次数还没有连接成功的状态）
                wifi_sta_disconnect();
                return 4;
                break;
            case CODE_WIFI_ON_GOT_IP:       //获取IP
                wifi_sta_ip4_addr_get(&ipv4_addr, NULL, NULL, NULL);
                LOG_I("CODE_WIFI_ON_GOT_IP\r\n");
                //LOG_I("wifi_sta_ip4_addr_get = %X\r\n",ipv4_addr);
                LOG_I("wifi_sta_ip4_addr_get = %d.%d.%d.%d\r\n",(uint8_t)ipv4_addr,(uint8_t)(ipv4_addr>>8),(uint8_t)(ipv4_addr>>16),(uint8_t)(ipv4_addr>>24));//uint8_t
                return 0;
            default:
                //等待连接成功
                break;
        }
    }
    return -1; //连接超时
}



static void wifi_connection()
{
    while (1) 
    {
        if (sta_ConnectStatus == CODE_WIFI_ON_MGMR_DONE) 
        { // WIFI管理初始化完毕
          if(wifi_connect()==0){
            sta_ConnectStatus1 = 1;
            LOG_I("wifi_connect() \r\n");
          }
          
         //   wifi_connect();
        }        
        vTaskDelay(3000/portTICK_PERIOD_MS);
    }
}


static void wifi_tcp_client_close()
{
    if (sock_client) {
        closesocket(sock_client);
    }

}

static void wifi_tcp_client_init(char *host_name,char *port)
{
    LOG_I("tcp client task start ...\r\n");
    char *addr;

    ip4_addr_t dns_ip;
    netconn_gethostbyname(host_name, &dns_ip);
    addr = ip_ntoa(&dns_ip);

   // while (1) {
        if ((sock_client = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
            LOG_E("TCP Client create socket error\r\n");
            return;
        }
        client_addr.sin_family = AF_INET;
        client_addr.sin_port = htons(atoi(port));
        client_addr.sin_addr.s_addr = inet_addr(addr);
        memset(&(client_addr.sin_zero), 0, sizeof(client_addr.sin_zero));

        printf("Server ip Address : %s:%s\r\n", addr, port);

        if (connect(sock_client, (struct sockaddr *)&client_addr, sizeof(struct sockaddr)) != 0) {
            LOG_E("TCP client connect server falied!\r\n");
            closesocket(sock_client);
            return;
        }

        LOG_I("TCP client connect server success!\r\n");

   // }
}
int wifi_tcp_client_send(const char *send_buf,uint8_t buf_size)
{   
   int cont = 0;
   if(sock_client){
      cont = write(sock_client, send_buf, buf_size) ;
            if (cont < 0) {
                LOG_E("write socket falied!\r\n");
                wifi_tcp_client_close(); 
                sock_client = -1; 
            }

   }
   return cont;
}

int wifi_tcp_client_recv(uint8_t *recv_buf)
{   
   int cont = 0;
   if(sock_client){
      cont = read(sock_client, recv_buf, MAXSIZE) ;
            if (cont < 0) {
                LOG_E("read socket falied!\r\n");
            }

   }
   return cont;
}

static void wifi_tcp_client_read()
{
    uint8_t recv_buf[1024]={0};
    while (1)
    {
        if((sock_client > 0)&&(sta_ConnectStatus1 ==  1)){

            int bufsize = wifi_tcp_client_recv(recv_buf);
            if(bufsize>0){          //处理接收到的数据
                recv_buf[bufsize+1]=0;
               LOG_I("read socket msg = [%s]\r\n",recv_buf);

            }else {
                LOG_I("wifi_tcp_client_close\r\n");
                wifi_tcp_client_close(); 
               sock_client = -1; 
            }
        }
        vTaskDelay(1000/portTICK_PERIOD_MS);
    }
    
}
static void wifi_tcp_client_creat()
{
    
    static uint8_t delay_cont = 0;
     while (1) 
    {
        delay_cont++;
        if (sta_ConnectStatus1 ==  1)	//连接成功(表示wifi sta状态的时候表示同时获取IP(DHCP)成功，或者使用静态IP)
        { 
        if(sock_client < 0){

                LOG_I("wifi_tcp_client_init\r\n");
                wifi_tcp_client_init(beserver_ip,beserver_port);
                if(sock_client){
                 wifi_tcp_client_send(subscribe,sizeof(subscribe)); //发送注册指令  
                }
        }
        if(delay_cont >=55){  //防止因为超过60秒，服务器关闭连接。
            delay_cont = 0;
            if(sock_client){
              LOG_I("wifi_tcp_client_send\r\n");
              wifi_tcp_client_send(Keep_alive_str,sizeof(Keep_alive_str)); //发送心跳数据  
            }
             
        }        
        }  


        vTaskDelay(1000/portTICK_PERIOD_MS);
    }
     wifi_tcp_client_close();   
}

int main(void)
{
    board_init();

    //uart0 = bflb_device_get_by_name("uart0");
    tcpip_init(NULL, NULL);
    wifi_start_firmware_task();
    xTaskCreate(wifi_connection, (char*)"wifi_connection", 1024, NULL, 1, NULL);   
    xTaskCreate(wifi_tcp_client_creat, (char*)"wifi_tcp_client_creat", 1024, NULL, 1, NULL); 
    xTaskCreate(wifi_tcp_client_read, (char*)"wifi_tcp_client_read", 1024, NULL, 1, NULL); 
    vTaskStartScheduler();

    while (1) {
    }
}
